/**
 * Session.cs
 * 
 * AUTHOR:
 * Zlatko Michailov (http://blogs.msdn.com/esql)
 * 
 * PURPOSE:
 * Maintains a session behind an eSQL script.
 * 
 * COPYRIGHT:
 * (c) Microsoft Corp., 2006-2007
 */



using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Data;
using System.Data.Common;
using System.Data.EntityClient;



namespace Microsoft.Samples.Data.eSqlBlast
{
    public class Session
    {
        // Data members
        private EntityConnection  _Connection = null;


        // Constructors
        public Session()
        {
            // Replace the DeafultTraceListener with an ExceptionTraceListener
            // to convert Debug.Assert() to exception.
            Debug.Listeners.Clear();
            Debug.Listeners.Add(new ExceptionTraceListener());
        }


        // Properties
        public IMultiReaderVisitor ResultVisitor = null;
        public EntityConnection Connection
        {
            get
            {
                return _Connection;
            }
        }


        public bool IsConnected
        {
            get
            {
                return _Connection != null && _Connection.State == ConnectionState.Open;
            }
        }


        // Methods
        public void Connect(string connectionString)
        {
            Disconnect();
            _Connection = new EntityConnection(connectionString);
            _Connection.Open();
        }


        public void Disconnect()
        {
            if (_Connection != null)
            {
                _Connection.Close();
                _Connection.Dispose();
                _Connection = null;
            }
        }


        public int Execute(string input)
        {
            CheckContext();

            ScriptParser parser = new ScriptParser(new eSql());
            parser.Parse(input);

            ResultVisitor.BeginBatch();
            foreach (Statement statement in parser.ExecutableStatements)
            {
                EntityCommand command = _Connection.CreateCommand();
                command.CommandText = statement.ToString();

                try
                {
                    ResultVisitor.VisitCommand(command);
                    EntityDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);
                    ResultVisitor.VisitReader(reader);
                }
                catch (Exception ex)
                {
                    ResultVisitor.VisitException(ex);
                }
            }
            ResultVisitor.EndBatch();
            
            return 0;
        }


        private void CheckContext()
        {
            if (ResultVisitor == null)
            {
                throw new InvalidOperationException("ResultVisitor must be set before Execute() may be invoked.");
            }

            if (Connection == null)
            {
                throw new InvalidOperationException("A connection must be extablished before attempting to execute a script.");
            }
        }

    }

}
